home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Languages / Masm V6.11 / SAMPLES / DEMOS / MISCDEMO.AS$ / MISCDEMO.bin
Encoding:
Text File  |  1993-07-26  |  36.8 KB  |  1,024 lines

  1. ;* MISCDEMO - Invokes many of the assembly example procedures, most of them
  2. ;* demonstrating assembly language instructions and calls to the system BIOS.
  3. ;* MISCDEMO demonstrates how to:
  4. ;*
  5. ;*         -   determine hardware information
  6. ;*         -   display time and date while waiting for keystrokes
  7. ;*         -   play notes of any frequency on the speaker
  8. ;*         -   change the line mode for EGA or VGA systems
  9. ;*         -   create nondestructive pop-up windows
  10. ;*         -   execute another program as a child process
  11. ;*         -   create primitive handlers for Interrupts 1Bh, 23h, and 24h
  12. ;*         -   use procedures callable by C in assembly programs
  13. ;*         -   use simplified segment directives
  14. ;*         -   write model-independent procedures
  15. ;*         -   declare and initialize data with DUP, BYTE, WORD, and DWORD
  16. ;*         -   create structures with the STRUCT directive
  17. ;*         -   declare macros
  18. ;*         -   set up a dispatch table
  19. ;*
  20. ;* MISCDEMO.EXE is built from the following files:
  21. ;*    MISCDEMO.ASM - Main program
  22. ;*    MISC.ASM     - Assembly procedures for MISCDEMO
  23. ;*    COMMON.ASM   - Assembly procedures shared by other example programs
  24. ;*    DEMO.INC     - Include file with macros, structure declarations
  25. ;*
  26. ;* Procedures:  GetVidConfig    GetCurPos       VeriPrint       GetPSP
  27. ;*              WinOpen         VeriAnsi        VeriCop         GetVer
  28. ;*              WinClose        StrWrite        SetLineMode     NewBlockSize
  29. ;*              SetCurSize      GetKeyClock     BinToHex        IntToAsc
  30. ;*              SetCurPos       GetShift        Sound           Colors
  31. ;*              GetCurSize      GetMem          Pause           Exec
  32. ;*              WriteTTY        Initialize
  33.  
  34.         .DOSSEG
  35.         .MODEL  small, pascal, os_dos
  36.         INCLUDE demo.inc
  37.  
  38. NewBreak        PROTO   FAR
  39. NewCtrlC        PROTO   FAR
  40. NewCritErr      PROTO   FAR
  41. DispMenu        PROTO   NEAR
  42. Press           PROTO   NEAR
  43. GetVidinfo      PROTO   NEAR
  44. GetMemInfo      PROTO   NEAR
  45. CheckPrinter    PROTO   NEAR
  46. CheckAnsi       PROTO   NEAR
  47. CheckCoproc     PROTO   NEAR
  48. GetConfig       PROTO   NEAR
  49. Speaker         PROTO   NEAR
  50. SetLines        PROTO   NEAR
  51. PopWindows      PROTO   NEAR
  52. SetAttrs        PROTO   NEAR
  53. ExecPgm         PROTO   NEAR
  54.  
  55.         .STACK
  56.         .DATA
  57.  
  58. PGMSIZE EQU     500h                    ; Maximum program size in paragraphs
  59. F1      EQU     59                      ; Extended code for first option key
  60. F7      EQU     65                      ; Extended code for last option key
  61. CLKROW  EQU     0                       ; Row for on-screen clock
  62. CLKCOL  EQU     62                      ; Column for on-screen clock
  63.  
  64. ;* Box - Macro to color portion of screen for effect. Not to be confused with
  65. ;* the WinOpen procedure, which is far more capable.
  66. ;*
  67. ;* Params:  Row1 - Screen row at top of box
  68. ;*          Col1 - Screen column at left side of box
  69. ;*          Row2 - Screen row at bottom of box
  70. ;*          Col2 - Screen column at right side of box
  71.  
  72. Box MACRO Row1, Col1, Row2, Col2
  73.     LOCAL sk
  74.     mov ax, 0600h                       ;; Scroll service
  75.     mov bh, Filmono                     ;; Fill attribute
  76.     .IF vconfig.adapter != MDA          ;; If color,
  77.     mov bh, Filcolr                     ;;   use color fill attribute
  78.     .ENDIF
  79.     mov ch, Row1
  80.     mov cl, Col1                        ;; CX = row/col for upper left
  81.     mov dh, Row2
  82.     mov dl, Col2                        ;; DX = row/col for lower right
  83.     int 10h                             ;; Blank window area on screen
  84. ENDM
  85.  
  86. OldMode BYTE    ?                       ; Original video mode
  87. OldCurs WORD    ?                       ; Original cursor coordinates
  88. KeepSeg PSEG    ?                       ; Segment addr, orig screen
  89. Filcolr BYTE    1Fh, 20h, 3Bh, 4Eh      ; Color fill attributes
  90. Filmono BYTE    70h, 89h, 78h, 1        ; Monochrome fill attributes
  91. Fill    BYTE    7                       ; Default attribute for menu
  92. Filsub  BYTE    ?                       ; Fore/background colors in submenu
  93.  
  94. PresMsg BYTE    ". . . press a key to continue", 0
  95. yes     BYTE    "yes"
  96. no      BYTE    "no "
  97.  
  98. ; Main menu text
  99.  
  100. Menu1   BYTE    "***  MISC Demonstration Program  ***", 0
  101. Menu2   BYTE    "F1  System Configuration", 0
  102. Menu3   BYTE    "F2  Speaker Test", 0
  103. Menu4   BYTE    "F3  Toggle Line Mode", 0
  104. Menu5   BYTE    "F4  Windows", 0
  105. Menu6   BYTE    "F5  Screen Colors", 0
  106. Menu7   BYTE    "F6  Exec Program", 0
  107. Menu8   BYTE    "Select an option, or press ESC to quit:", 0
  108.  
  109. ; Option F1 - System Configuration
  110.  
  111. MonoStr BYTE    "monochrome"
  112. ClrStr  BYTE    "color     "
  113. AdapStr BYTE    "MDA CGA MCGAEGA VGA "
  114. VidMsg1 BYTE    "Adapter:                 xxxx", 0
  115. VidMsg2 BYTE    "Display:                 xxxxxxxxxx", 0
  116. VidMsg3 BYTE    "Mode:                    xx", 0
  117. VidMsg4 BYTE    "Rows:                    xx", 0
  118. MemMsg1 BYTE    "Total memory:            xxxx Kb", 0
  119. MemMsg2 BYTE    "Available memory:        xxxx Kb", 0
  120. PrnMsg  BYTE    "Printer ready:           xxx", 0
  121. AnsiMsg BYTE    "ANSI driver installed:   xxx", 0
  122. CopMsg  BYTE    "Coprocessor installed:   xxx", 0
  123. LEN1    EQU     LENGTHOF CopMsg - 4
  124.  
  125. ; Option F3 - Toggle Line Mode
  126.  
  127. LineMsg BYTE    "Line mode reset available only for EGA or VGA", 0
  128.  
  129. ; Option F4 - Windows
  130.  
  131. WinMsg  BYTE    "WINDOW x", 0
  132. LEN3    EQU     LENGTHOF WinMsg - 2
  133.  
  134. ; Option F5  Screen Colors
  135.  
  136. CMsg1   BYTE    "Toggle                   Step", 0
  137. CMsg2   BYTE    "────────────────         ──────────────────", 0
  138. CMsg3   BYTE    "B  blink                 ", 27, 26, "  foreground", 0
  139. CMsg4   BYTE    "I  intensity             ", 24, 25, "  background", 0
  140. CMsg5   BYTE    "Foreground:  press F, then color number 0-7", 0
  141. CMsg6   BYTE    "Background:  press A, then color number 0-7", 0
  142. CMsg7   BYTE    "Color Numbers", 0
  143. CMsg8   BYTE    "───────────────────────────────────────────", 0
  144. CMsg9   BYTE    "0  black                     4  red", 0
  145. CMsg10  BYTE    "1  blue                      5  magenta", 0
  146. CMsg11  BYTE    "2  green                     6  brown", 0
  147. CMsg12  BYTE    "3  cyan                      7  white", 0
  148. CMsg13  BYTE    "Toggle", 0
  149. CMsg14  BYTE    "───────────────", 0
  150. CMsg15  BYTE    "B  blink", 0
  151. CMsg16  BYTE    "I  intensity", 0
  152. CMsg17  BYTE    "U  underline", 0
  153. CMsg18  BYTE    "R  reverse", 0
  154.  
  155. ; Option F6 - Exec Program
  156.  
  157. RetMsg  BYTE    "Return code:  "
  158. Recode  BYTE    6 DUP (?)               ; ASCII string for return code
  159. ExecMsg BYTE    "Enter program file spec (including .COM or .EXE):", 0
  160. TailMsg BYTE    "Enter command-line argument(s):", 0
  161. Fspec   BYTE    50, 50 DUP (?)          ; File specification (max length = 50)
  162. Tail    BYTE    50, 50 DUP (?)          ; Command-line tail (max length = 50)
  163. Fcblk1  BYTE    0                       ; Allocate space for 1st FCB
  164.         BYTE    11 DUP (0)
  165.         BYTE    25 DUP (0)
  166. Fcblk2  BYTE    0                       ; Allocate space for 2nd FCB
  167.         BYTE    11 DUP (0)
  168.         BYTE    25 DUP (0)
  169. pb      PARMBLK <>                      ; Parameter block structure
  170.  
  171. ; Initialize dispatch table with offsets for internal procedures.
  172.  
  173. TPROC   TYPEDEF PROTO           ; Procedure type
  174. PPROC   TYPEDEF PTR TPROC       ; Pointer to procedure with no arguments
  175.  
  176. ; Table of procedures
  177. DispTbl PPROC   GetConfig, Speaker, SetLines,
  178.                 PopWindows, SetAttrs, ExecPgm
  179.  
  180.         .CODE
  181.         .STARTUP
  182.  
  183.         ; Initialize _psp and _env variables
  184.         INVOKE  Initialize
  185.  
  186.         ; Return unused memory to DOS
  187.         ; Pass PSP segment address and memory block allocated to program
  188.         INVOKE  NewBlockSize, _psp, PGMSIZE
  189.  
  190.         ; Initialize global configuration data
  191.         INVOKE  GetVidConfig
  192.  
  193.         mov     al, vconfig.rows
  194.         mov     OldMode, al             ; Preserve original line mode
  195.  
  196.         ; Get current cursor position
  197.         INVOKE  GetCurPos
  198.  
  199.         mov     OldCurs, ax             ; Store it
  200.  
  201.         ; Preserve original screen and put up window
  202.         ; Pass top, left, bottom, right, and attribute
  203.         INVOKE  WinOpen, 0, 0, vconfig.rows, 79, 07h
  204.  
  205.         mov     KeepSeg, ax             ; Keep segment address
  206.         .IF     AX == 0                 ; If window not opened successfully,
  207.         .EXIT   1                       ;   exit with return code = 1
  208.         .ENDIF
  209.  
  210.         .WHILE 1
  211.  
  212.         ; Display main menu
  213.         INVOKE  DispMenu
  214.  
  215.         ; Highlight on-screen clock with macro
  216.         Box CLKROW, CLKCOL-1, CLKROW, CLKCOL + 17
  217.  
  218.         ; Poll for keyboard selection while updating time
  219.         ; Pass row and column
  220.         INVOKE  GetKeyClock, CLKROW, CLKCOL
  221.  
  222.         .BREAK .IF al == ESCAPE         ; Quit loop if ESC key
  223.  
  224.         .CONTINUE .IF (ah < F1) || (ah > F7) ; Ignore if not a function
  225.                                              ;   key between F1 and F7?
  226.  
  227.         xchg    al, ah                  ; Yes?  Make AX = AH
  228.         sub     al, F1                  ; Normalize to 0
  229.         shl     al, 1                   ; Double to make word index
  230.         mov     bx, ax                  ; BX = index to table
  231.  
  232.         ; Call the current procedure from call table
  233.         INVOKE  DispTbl[bx]
  234.  
  235.         .ENDW                           ; Loop for another key
  236.  
  237.         mov     al, OldMode             ; Get original line mode
  238.         .IF     al != vconfig.rows      ; If not same as current mode,
  239.  
  240.         inc     ax                      ;   increment to 25/43/50
  241.  
  242.         ; Restore line mode, pass lines
  243.         INVOKE  SetLineMode, ax
  244.  
  245.         .ENDIF
  246.  
  247.         ; Restore original screen, pass segment of screen contents
  248.         INVOKE  WinClose, KeepSeg
  249.  
  250.         mov     ax, OldCurs
  251.  
  252.         ; Restore cursor to original place
  253.         ; Pass row and column
  254.         INVOKE  SetCurPos, BYTE PTR OldCurs[1], BYTE PTR OldCurs[0]
  255.  
  256.         .EXIT   0                       ; Exit wih return code 0
  257.  
  258.  
  259. ;* DispMenu - Displays main menu.
  260. ;*
  261. ;* Uses:    vconfig - Video configuration structure (initialized
  262. ;*          by calling the GetVidConfig procedure)
  263. ;*
  264. ;* Return:  None
  265.  
  266. DispMenu PROC NEAR
  267.  
  268.         mov     ax, 0600h               ; Scroll screen service
  269.         mov     bh, Fill                ; Menu display attribute
  270.         sub     cx, cx                  ; From row 0, col 0
  271.         mov     dh, vconfig.rows        ;   to bottom row,
  272.         mov     dl, 79                  ;   rightmost column
  273.         int     10h                     ; Clear entire screen
  274.  
  275.         ; Display menu
  276.         ; For each line pass row, column, and string address
  277.         INVOKE StrWrite,  4, 21, ADDR Menu1
  278.         INVOKE StrWrite,  8, 28, ADDR Menu2
  279.         INVOKE StrWrite,  9, 28, ADDR Menu3
  280.         INVOKE StrWrite, 10, 28, ADDR Menu4
  281.         INVOKE StrWrite, 11, 28, ADDR Menu5
  282.         INVOKE StrWrite, 12, 28, ADDR Menu6
  283.         INVOKE StrWrite, 13, 28, ADDR Menu7
  284.         INVOKE StrWrite, 17, 18, ADDR Menu8
  285.  
  286.         ; Park cursor at prompt, pass row and column
  287.         INVOKE  SetCurPos, 17, 18 + (LENGTHOF Menu8) + 2
  288.  
  289.         ret
  290.  
  291. DispMenu ENDP
  292.  
  293.  
  294.  
  295. ;* Press - Displays a prompt, then waits for a key press.
  296. ;*
  297. ;* Uses:    vconfig - Video configuration structure (initialized
  298. ;*          by calling the GetVidConfig procedure)
  299. ;*
  300. ;* Return:  None
  301.  
  302. Press   PROC NEAR
  303.  
  304.         ; Write string, pass row, column, and string address
  305.         INVOKE StrWrite, vconfig.rows, 50, ADDR PresMsg
  306.  
  307.         ; Park cursor at prompt, pass row and column
  308.         INVOKE  SetCurPos, vconfig.rows, 48
  309.  
  310.         ; Poll for keyboard selection while updating time
  311.         ; Pass row and column
  312.         INVOKE  GetKeyClock, CLKROW, CLKCOL
  313.  
  314.         ret
  315.  
  316. Press   ENDP
  317.  
  318.  
  319.  
  320. ;* GetVidinfo - Initializes video configuration message for display.
  321. ;*
  322. ;* Uses:    vconfig - Video configuration structure (initialized
  323. ;*          by calling the GetVidConfig procedure)
  324. ;*
  325. ;* Return:  None
  326.  
  327. GetVidinfo PROC NEAR
  328.  
  329.         push    ds
  330.         pop     es                      ; Point ES to data segment
  331.         mov     al, 4                   ; Find index to 4-character
  332.         mul     vconfig.adapter         ;   group in string
  333.         add     ax, OFFSET AdapStr      ; Point AX to proper group
  334.         mov     si, ax                  ; Put pointer in SI
  335.         lea     di, VidMsg1[LEN1]       ; Point to 1st line of message
  336.         mov     cx, 2                   ; Copy 4 letters (adapter
  337.         rep     movsw                   ;   designation) to message
  338.  
  339.         mov     si, OFFSET MonoStr      ; Assume display is monochrome
  340.         .IF     vconfig.display != MONO ; If color display,
  341.         mov     si, OFFSET ClrStr       ;   point to "color" string
  342.         .ENDIF
  343.         lea     di, VidMsg2[LEN1]       ; Point to 2nd line of message
  344.         mov     cx, 5                   ; Copy 10 chars ("monochrome"
  345.         rep     movsw                   ;   or "color     ") to msg
  346.  
  347.         ; Note that IntToAsc can't be invoked because of its
  348.         ; register calling convention
  349.         mov     al, vconfig.mode
  350.         cbw                             ; AX = video mode
  351.         call    IntToAsc                ; Convert AX to ASCII
  352.         xchg    ah, al                  ; Flip bytes for word write
  353.         mov     WORD PTR VidMsg3[LEN1], ax  ; Insert in message string
  354.  
  355.         mov     al, vconfig.rows
  356.         cbw
  357.         inc     ax                      ; AX = number of screen rows
  358.         call    IntToAsc                ; Convert to ASCII
  359.         xchg    ah, al                  ; Flip bytes for word write
  360.         mov     WORD PTR VidMsg4[LEN1], ax  ; Insert in message string
  361.         ret
  362.  
  363. GetVidinfo ENDP
  364.  
  365.  
  366.  
  367. ;* GetMemInfo - Initializes memory information message.
  368. ;*
  369. ;* Return:  None
  370.  
  371. GetMemInfo PROC NEAR
  372.  
  373.         ; Get total memory in DX, available memory in AX
  374.         INVOKE  GetMem
  375.  
  376.         push    ax
  377.         mov     ax, dx
  378.         call    IntToAsc                ; Convert AX to ASCII
  379.         xchg    dh, dl                  ; Flip bytes for word write
  380.         xchg    ah, al
  381.         mov     WORD PTR MemMsg1[LEN1], dx      ; Insert in message
  382.         mov     WORD PTR MemMsg1[LEN1+2], ax    ;   string
  383.         pop     ax                              ; Recover avail memory #
  384.         call    IntToAsc                        ; Convert to ASCII
  385.         xchg    dh, dl                          ; Flip bytes for word write
  386.         xchg    ah, al
  387.         mov     WORD PTR MemMsg2[LEN1], dx      ; Insert in message
  388.         mov     WORD PTR MemMsg2[LEN1+2], ax    ;   string
  389.         ret
  390.  
  391. GetMemInfo ENDP
  392.  
  393.  
  394. ;* CheckPrinter - Initializes printer status message.
  395. ;*
  396. ;* Shows:   Instruction - movsb
  397. ;*
  398. ;* Return:  None
  399.  
  400. CheckPrinter PROC NEAR
  401.  
  402.         push    ds
  403.         pop     es                      ; Point ES to data segment
  404.         mov     si, OFFSET yes          ; Assume answer is "yes"
  405.  
  406.         ; Check if printer ready
  407.         INVOKE  VeriPrint
  408.  
  409.         .IF     al == 0                 ; If not ready,
  410.         mov     si, OFFSET no           ;   point to "no" answer
  411.         .ENDIF
  412.         lea     di, PrnMsg[LEN1]        ; Point to print message
  413.         mov     cx, 3                   ; Copy 3 letters (either "yes"
  414.         rep     movsb                   ;   or "no ") to message
  415.         ret
  416.  
  417. CheckPrinter ENDP
  418.  
  419.  
  420.  
  421. ;* CheckAnsi - Initializes status message for ANSI driver.
  422. ;*
  423. ;* Return:  None
  424.  
  425. CheckAnsi PROC NEAR
  426.  
  427.         push    ds
  428.         pop     es                      ; Point ES to data segment
  429.         mov     si, OFFSET yes          ; Assume answer is "yes"
  430.  
  431.         ; Check if ANSI driver is installed
  432.         INVOKE  VeriAnsi
  433.  
  434.         .IF     al == 0                 ; If not installed,
  435.         mov     si, OFFSET no           ;   point to "no" answer
  436.         .ENDIF
  437.         lea     di, AnsiMsg[LEN1]       ; Point to ansi message
  438.         mov     cx, 3                   ; Copy 3 letters (either "yes"
  439.         rep     movsb                   ;   or "no ") to message
  440.         ret
  441.  
  442. CheckAnsi ENDP
  443.  
  444.  
  445.  
  446. ;* CheckCoproc - Initializes coprocessor status message.
  447. ;*
  448. ;* Return:  None
  449.  
  450. CheckCoproc PROC NEAR
  451.  
  452.         push    ds
  453.         pop     es                      ; Point ES to data segment
  454.         mov     si, OFFSET yes          ; Assume answer is "yes"
  455.  
  456.         ; Check for coprocessor
  457.         INVOKE  VeriCop
  458.  
  459.         .IF     al == 0                 ; If not installed:
  460.         mov     si, OFFSET no           ; Point to "no" answer
  461.         .ENDIF
  462.         lea     di, CopMsg[LEN1]        ; Point to coprocessor message
  463.         mov     cx, 3                   ; Copy 3 letters (either "yes"
  464.         rep     movsb                   ;   or "no ") to message
  465.         ret
  466.  
  467. CheckCoproc ENDP
  468.  
  469.  
  470. ;* GetConfig - Displays system configuration information.
  471.  
  472. GetConfig PROC NEAR
  473.  
  474.         INVOKE  GetVidinfo              ; Initialize video message
  475.         INVOKE  GetMemInfo              ; Initialize memory message
  476.         INVOKE  CheckPrinter            ; Initialize printer message
  477.         INVOKE  CheckAnsi               ; Initialize ANSI driver msg
  478.         INVOKE  CheckCoproc             ; Initialize coprocessor msg
  479.  
  480.         Box 4, 13, 20, 67               ; Clear screen with box
  481.  
  482.         ; Display configuration information
  483.         ; For each line, pass row, column, and string address
  484.         INVOKE  StrWrite,  6, 23, ADDR VidMsg1
  485.         INVOKE  StrWrite,  7, 23, ADDR VidMsg2
  486.         INVOKE  StrWrite,  8, 23, ADDR VidMsg3
  487.         INVOKE  StrWrite,  9, 23, ADDR VidMsg4
  488.         INVOKE  StrWrite, 11, 23, ADDR MemMsg1
  489.         INVOKE  StrWrite, 12, 23, ADDR MemMsg2
  490.         INVOKE  StrWrite, 14, 23, ADDR PrnMsg
  491.         INVOKE  StrWrite, 16, 23, ADDR AnsiMsg
  492.         INVOKE  StrWrite, 18, 23, ADDR CopMsg
  493.  
  494.         ; Prompt for keypress
  495.         INVOKE  Press
  496.  
  497.         ret
  498.  
  499. GetConfig ENDP
  500.  
  501.  
  502.  
  503. ;* Speaker - Sounds speaker with ascending frequencies.
  504. ;*
  505. ;* Return:  None
  506.  
  507. Speaker PROC NEAR
  508.  
  509.         sub     ax, ax
  510.         .REPEAT
  511.         add     ax, 100                 ; Start with frequency 100
  512.         push    ax                      ; Save frequency
  513.  
  514.         ; Beep speaker, pass frequency and duration
  515.         INVOKE  Sound, ax, 1
  516.  
  517.         pop     ax                      ; Recover frequency
  518.         .UNTIL  ax > 3000               ; Continue to frequency 3000
  519.         ret
  520.  
  521. Speaker ENDP
  522.  
  523.  
  524.  
  525. ;* SetLines - Toggles between 25/43-line mode for EGA or 25/43/50-line mode
  526. ;* for VGA.
  527. ;*
  528. ;* Uses:    vconfig - Video configuration structure (initialized
  529. ;*          by calling the GetVidConfig procedure)
  530. ;*
  531. ;* Return:  None
  532.  
  533. SetLines PROC NEAR
  534.  
  535.         mov     al, 25                  ; Assume toggle to 25 line
  536.         cmp     vconfig.rows, 49        ; Current mode 50 lines?
  537.         je      toggle25                ; Yes?  Toggle VGA to 25-line
  538.         cmp     vconfig.rows, 42        ; Current mode 43 lines?
  539.         jne     toggle43                ; No?  Must be 25
  540.         cmp     vconfig.adapter, EGA    ; Yes?  And is adapter EGA?
  541.         je      toggle25                ; Yes?  Then toggle to 25 line
  542.         mov     al, 50                  ; No?  Toggle VGA to 50 line
  543.         jmp     toggle25
  544. toggle43:
  545.         mov     al, 43                  ; If currently 25 lines, make
  546.                                         ;   either EGA or VGA 43 lines
  547. toggle25:
  548.         ; Change line mode, pass lines
  549.         INVOKE  SetLineMode, ax
  550.  
  551.         .IF     al == 0                 ; If no error,
  552.         INVOKE  GetVidConfig            ;   update configuration structure
  553.         .ELSE                           ; Else,
  554.         Box 16, 13, 20, 67              ;   display error message
  555.  
  556.         ; Write line message, pass row, column, and string address
  557.         INVOKE  StrWrite, 18, 17, ADDR LineMsg
  558.  
  559.         INVOKE  Press
  560.         .ENDIF
  561.  
  562.         ret
  563.  
  564. SetLines ENDP
  565.  
  566.  
  567.  
  568. ;* PopWindows - Demonstrates windowing with the WinOpen and WinClose
  569. ;* procedures.
  570. ;*
  571. ;* Uses:    vconfig - Video configuration structure (initialized
  572. ;*          by calling the GetVidConfig procedure)
  573. ;*
  574. ;* Return:  None
  575.  
  576. PopWindows PROC NEAR
  577.  
  578.         LOCAL Row1:WORD, Col1:WORD, Row2:WORD, Col2:WORD
  579.         LOCAL Index:BYTE, Adr[4]:WORD, Csize:WORD
  580.  
  581.         ; Get current cursor size
  582.         INVOKE  GetCurSize
  583.  
  584.         mov     Csize, ax               ; Store it
  585.         or      al, 100000y             ; Set 5th bit for cursor off
  586.         mov     bl, al
  587.  
  588.         ; Set cursor size
  589.         ; Pass arbitrary top and bottom lines with visibility bit off
  590.         INVOKE  SetCurSize, BYTE PTR Csize[1], bl
  591.  
  592.         mov     WinMsg[LEN3], "0"       ; Initialize window message
  593.         mov     Row1, 4                 ; Initialize window coords
  594.         mov     Col1, 10
  595.         mov     Row2, 20
  596.         mov     Col2, 34
  597.         mov     Index, 0
  598.         mov     cx, 4                   ; Open 4 windows
  599.         .REPEAT
  600.         push    cx                      ; Save loop counter
  601.         mov     al, Index
  602.         mov     bx, OFFSET Filmono      ; BX points to fill attributes
  603.         .IF     vconfig.display != MONO ; If not monochrome,
  604.         mov     bx, OFFSET Filcolr      ;   repoint to color attributes
  605.         .ENDIF
  606.         xlat                            ; Get attributes in succession
  607.  
  608.         ; Save old window and open new
  609.         ; Pass top, left, bottom, right, and attribute in AX
  610.         INVOKE  WinOpen, Row1, Col1, Row2, Col2, ax
  611.  
  612.         pop     di                      ; Recover counter in DI
  613.         push    di                      ;   and save it again
  614.         dec     di
  615.         shl     di, 1                   ; Make DI a word index
  616.         mov     Adr[di], ax             ; Save address of allocated
  617.                                         ;   block returned by WinOpen
  618.         inc     WinMsg[LEN3]            ; Increment window number
  619.         mov     bx, Row1
  620.         add     bl, 2                   ; Message row
  621.         mov     cx, Col1
  622.         add     cl, 9                   ; Message column
  623.  
  624.         ; Write window message, pass row, column, and string address
  625.         INVOKE StrWrite, bx, cx, ADDR WinMsg
  626.  
  627.         ; Pause, pass 18 ticks (about 1 second)
  628.         INVOKE  Pause, 18
  629.  
  630.         add     Row1, 2                 ; Adjust coordinates for
  631.         add     Col1, 13                ;   next window
  632.         sub     Row2, 2
  633.         add     Col2, 13
  634.         inc     Index
  635.         pop     cx                      ; Recover counter
  636.         .UNTILCXZ
  637.  
  638.         mov     cx, 4                   ; Close 4 windows
  639.         sub     di, di                  ; DI = index to addresses
  640.  
  641.         .REPEAT
  642.         push    cx                      ; Save loop counter
  643.  
  644.         ; Close a window, pass address of the window
  645.         INVOKE  WinClose, Adr[di]
  646.  
  647.         ; Pause, pass 18 ticks (about 1 second)
  648.         INVOKE  Pause, 18
  649.  
  650.         add     di, 2                   ; Point to next address
  651.         pop     cx                      ; Recover counter
  652.         .UNTILCXZ                       ; Close another window
  653.  
  654.         mov     ax, Csize               ; Get original cursor size
  655.  
  656.         ; Set cursor size, pass top and bottom lines
  657.         INVOKE  SetCurSize, BYTE PTR Csize[1], BYTE PTR Csize[0]
  658.  
  659.         ret
  660.  
  661. PopWindows ENDP
  662.  
  663.  
  664.  
  665. ;* SetAttrs - Changes display attributes for the main menu.
  666. ;*
  667. ;* Uses:    vconfig - Video configuration structure (initialized
  668. ;*          by calling the GetVidConfig procedure)
  669. ;*
  670. ;* Return:  None
  671.  
  672. SetAttrs PROC NEAR
  673.  
  674.         Box 3, 12, 23, 68
  675.         .IF     vconfig.adapter == MDA  ; If monochrome?
  676.  
  677.         ; Write monochrome menu
  678.         ; For each line, pass row, column, and string address
  679.         INVOKE StrWrite,  8, 32, ADDR CMsg13
  680.         INVOKE StrWrite,  9, 32, ADDR CMsg14
  681.         INVOKE StrWrite, 10, 36, ADDR CMsg15
  682.         INVOKE StrWrite, 11, 36, ADDR CMsg16
  683.         INVOKE StrWrite, 12, 36, ADDR CMsg17
  684.         INVOKE StrWrite, 13, 36, ADDR CMsg18
  685.  
  686.         mov     al, Filmono             ; Initialize Filsub variable
  687.         mov     Filsub, al              ;   for monochrome
  688.  
  689.         .ELSE
  690.  
  691.         ; Write color menu
  692.         ; For each line, pass row, column, and string address
  693.         INVOKE StrWrite,  4, 18, ADDR CMsg1
  694.         INVOKE StrWrite,  5, 18, ADDR CMsg2
  695.         INVOKE StrWrite,  6, 22, ADDR CMsg3
  696.         INVOKE StrWrite,  7, 22, ADDR CMsg4
  697.         INVOKE StrWrite, 10, 18, ADDR CMsg5
  698.         INVOKE StrWrite, 11, 18, ADDR CMsg6
  699.         INVOKE StrWrite, 14, 18, ADDR CMsg7
  700.         INVOKE StrWrite, 15, 18, ADDR CMsg8
  701.         INVOKE StrWrite, 16, 22, ADDR CMsg9
  702.         INVOKE StrWrite, 17, 22, ADDR CMsg10
  703.         INVOKE StrWrite, 18, 22, ADDR CMsg11
  704.         INVOKE StrWrite, 19, 22, ADDR CMsg12
  705.  
  706.         mov     al, Filcolr             ; Initialize Filsub variable
  707.         mov     Filsub, al              ;   for color
  708.         .ENDIF
  709.  
  710.         ; Write menu message
  711.         INVOKE StrWrite, 22, 15, ADDR Menu8
  712.  
  713.         ; Park cursor at prompt, pass row and column
  714.         INVOKE  SetCurPos, 22, 56
  715.  
  716.         .WHILE   1
  717.  
  718.         ; Poll for keyboard selection while updating time
  719.         ; Pass row and column
  720.         INVOKE  GetKeyClock, CLKROW, CLKCOL
  721.  
  722.         .BREAK .IF al == ESCAPE         ; Quit if ESC key
  723.  
  724.         .IF (al >= 'a') && (al <= 'z')  ; Convert letters to uppercase
  725.         and     al, 5Fh                 ;   to make comparisons easier
  726.         .ENDIF
  727.  
  728.         cmp     al, 'B'                 ; Request blink toggle?
  729.         je      blink
  730.         cmp     al, 'I'                 ; Request intensity toggle?
  731.         je      intense
  732.         mov     bl, Filsub              ; Get window display attribute
  733.         cmp     vconfig.adapter, MDA    ; Monochrome?
  734.         jne     iscolor                 ; No?  Jump to color selections
  735.         cmp     al, 'U'                 ; Request underline toggle?
  736.         je      underline
  737.         .CONTINUE .IF al != 'R'         ; If not reverse toggle,
  738.                                         ;   skip invalid key
  739.  
  740. ; With cross-toggling between reverse, normal, and underline, three
  741. ; bit settings can exist in monochrome:  x111x000 for reverse, x000x111 for
  742. ; normal, and x000x001 for underline. Changing between the three involves
  743. ; more than simply using XOR to determine the current attribute; each
  744. ; condition must check for the other two.
  745.  
  746. reverse:
  747.         .IF     bl & 1                  ; If reverse video off,
  748.         or      bl, 00000111y           ;   ensure normal bits are on
  749.         .ENDIF
  750.  
  751.         xor     bl, 01110111y           ; Toggle for reverse/normal
  752.         mov     cl, 6                   ; Set code for MOV
  753.         jmp     switch
  754.  
  755. underline:
  756.         .IF     bl & 1                  ; If reverse video on,
  757.         and     bl, 10001111y           ;   clear bits 4-6
  758.         or      bl, 00000111y           ;   and set bits 0-2
  759.         .ENDIF
  760.  
  761.         xor     bl, 00000110y           ; Toggle bits 1-2 for underline
  762.         mov     cl, 6                   ; Set code for MOV
  763.         jmp     switch
  764.  
  765. ; Blink and intensity use the same bits for color and monochrome.
  766.  
  767. blink:
  768.         mov     bl, 10000000y           ; Set bit 7 for blink
  769.         mov     cl, 4                   ; Set code for XOR
  770.         jmp     switch
  771.  
  772. intense:
  773.         mov     bl, 00001000y           ; Set bit 3 for intensity
  774.         mov     cl, 4                   ; Set code for XOR
  775.         jmp     switch
  776.  
  777. ; Enter this section only for color displays. First check for arrow keys,
  778. ; which increment or decrement the foreground or background bits of the
  779. ; current attribute stored in the variable Filsub. If arrow keys are not
  780. ; pressed, check for the F or A keys, which request specific colors for the
  781. ; foreground or background colors.
  782.  
  783. iscolor:
  784.         mov     ch, bl                  ; Copy current attribute to CH
  785.         .IF     ah == 72                ; If up arrow,
  786.         mov     cl, 4                   ;   increment bits 4-6
  787.         shr     ch, cl                  ;   to next background color
  788.         inc     ch
  789.         and     ch, 00000111y
  790.         shl     ch, cl
  791.         mov     dl, 10001111y           ; Set background mask
  792.         jmp     step
  793.         .ENDIF
  794.  
  795.         .IF     ah == 75                ; If left arrow,
  796.         inc     ch                      ;   increment bits 0-2
  797.         and     ch, 00000111y           ;   to next foreground color
  798.         mov     dl, 11111000y           ; Set foreground mask
  799.         jmp     step
  800.         .ENDIF
  801.  
  802.         .IF     ah == 77                ; If right arrow,
  803.         dec     ch                      ;   decrement bits 0-2
  804.         and     ch, 00000111y           ;   to previous foreground color
  805.         mov     dl, 11111000y           ; Set foreground mask
  806.         jmp     step
  807.         .ENDIF
  808.  
  809.         .IF     ah == 80                ; If down arrow,
  810.         mov     cl, 4                   ;   decrement bits 4-6
  811.         shr     ch, cl                  ;   to previous background color
  812.         dec     ch
  813.         and     ch, 00000111y
  814.         shl     ch, cl
  815.         mov     dl, 10001111y           ; Set background mask
  816. step:
  817.         and     bl, dl                  ; Mask out fore or back bits
  818.         or      bl, ch                  ; Copy into original attribute
  819.         mov     Filsub, bl              ; Store the new submenu color
  820.         mov     cl, 6                   ; Request move operation in
  821.         jmp     switch                  ;   Colors procedure
  822.         .ENDIF
  823.  
  824. ; This section checks for the F or A keys; if found it checks again for
  825. ; a number key between 0 and 7, then inserts the correct foreground or
  826. ; background bit pattern into the current fill attribute.
  827.  
  828.         sub     cx, cx                  ; Clear flag for foreground request
  829.         .IF     al == 'A'               ; If background request,
  830.         inc     cx                      ;   set flag for background request
  831.         .ELSE
  832.         .CONTINUE .IF al != 'F'         ; If not foreground request, continue
  833.         .ENDIF
  834.  
  835.         push    cx
  836.  
  837.         ; Poll for keyboard selection while updating time
  838.         ; Pass row and column
  839.         INVOKE  GetKeyClock, CLKROW, CLKCOL
  840.  
  841.         pop     cx                      ; Recover flag
  842.  
  843.         .CONTINUE .IF (al < '0') || (al > '7') ; Ignore invalid key
  844.  
  845.         xor     al, '0'                 ; Convert ASCII numeral into binary
  846.         mov     dl, 11111000y           ; Set foreground mask
  847.         .IF     cx != 0                 ; Skip if foreground request
  848.         mov     cl, 4                   ; Otherwise shift bits 0-2
  849.         shl     al, cl                  ;   to positions 4-6
  850.         mov     dl, 10001111y           ; Set background mask
  851.         .ENDIF
  852.  
  853.         mov     bl, Filsub
  854.         and     bl, dl                  ; Mask out fore or back bits
  855.         or      bl, al                  ; Insert number into fore or back bits
  856.         mov     Filsub, bl              ; Store the new submenu color
  857.         mov     cl, 6                   ; Request move
  858. switch:
  859.  
  860.         ; Set new attributes in a window
  861.         ; Pass logic code (CX), attribute (BX), top, left, bottom, right
  862.         INVOKE  Colors, cx, bx, 3, 12, 23, 68
  863.  
  864.         mov     ah, 8                   ; Function 8, get char/attribute
  865.         mov     bh, vconfig.dpage
  866.         int     10h                     ; Get attribute in AH
  867.         mov     Fill, ah                ; New fill variable for main menu
  868.         mov     Filsub, ah              ;   and for submenu
  869.         .ENDW
  870.         ret
  871.  
  872. SetAttrs ENDP
  873.  
  874.  
  875.  
  876. ;* ExecPgm - Executes a specified program as a child process.
  877. ;*
  878. ;* Uses:    vconfig - Video configuration structure (initialized
  879. ;*          by calling the GetVidConfig procedure)
  880. ;*          pb - Parameter block structure, declared in the DEMO.INC file
  881. ;*
  882. ;* Return:  None
  883.  
  884. ExecPgm PROC NEAR
  885.  
  886.         Box 16, 13, 20, 67
  887.  
  888.         ; Display prompt for file spec, pass row, column, and string address
  889.         INVOKE StrWrite, 17, 16, ADDR ExecMsg
  890.  
  891.         ; Set cursor position below prompt, pass row and column
  892.         INVOKE  SetCurPos, 19, 16
  893.  
  894.         mov     ah, 0Ah                 ; Request DOS to read keyboard
  895.         mov     dx, OFFSET Fspec        ;   input into Fspec string
  896.         int     21h                     ; Read Buffered Keyboard Input
  897.  
  898.         Box 16, 13, 20, 67
  899.  
  900.         ; Display prompt for command tail
  901.         INVOKE StrWrite, 17, 16, ADDR TailMsg
  902.  
  903.         ; Set cursor position below prompt, pass row and column
  904.         INVOKE  SetCurPos, 19, 16
  905.  
  906.         mov     ah, 0Ah                 ; Request DOS to read keyboard
  907.         mov     dx, OFFSET Tail         ;   input into tail string
  908.         int     21h                     ; Read Buffered Keyboard Input
  909.  
  910.         sub     bh, bh                  ; Clear BH
  911.         mov     si, OFFSET Fspec        ; DS:SI points to file spec string
  912.         mov     bl, [si+1]              ; BL = number of chars in spec
  913.         mov     BYTE PTR [si+bx+2], 0   ; Terminate string with 0
  914.  
  915.         mov     ax, _env                ; Get segment address of environment
  916.         mov     pb.env, ax              ; Copy it to parameter block
  917.         mov     ax, @data               ; AX points to data segment
  918.         lea     bx, Tail[1]             ; BX points to command-line tail
  919.         mov     WORD PTR pb.taddr[0], bx; Copy address of command-line tail
  920.         mov     WORD PTR pb.taddr[2], ax;   to parameter block
  921.  
  922.         mov     bx, OFFSET Fcblk1       ; BX points to first FCB
  923.         mov     WORD PTR pb.fcb1[0], bx ; Copy address of first FCB
  924.         mov     WORD PTR pb.fcb1[2], ax ;   to parameter block
  925.         mov     bx, OFFSET Fcblk2       ; BX points to second FCB
  926.         mov     WORD PTR pb.fcb2[0], bx ; Copy address of second FCB
  927.         mov     WORD PTR pb.fcb2[2], ax ;   to parameter block
  928.  
  929. ; At this point, the program file is specified, the command-line tail is set,
  930. ; and the parameter block is properly initialized. The Exec procedure will
  931. ; take care of loading the FCBs with command-line arguments and resetting
  932. ; interrupt vectors. Now blank the screen in preparation for executing the
  933. ; process and pass the five pointers to the Exec procedure.
  934.  
  935.         mov     ax, 0600h               ; AH = scroll service, AL = 0
  936.         mov     bh, 7                   ; Blank with normal attribute
  937.         sub     cx, cx                  ; From row 0, col 0
  938.         mov     dh, vconfig.rows        ;   to bottom row
  939.         mov     dl, 79                  ;   and rightmost column
  940.         int     10h                     ; Blank screen
  941.  
  942.         ; Set cursor at top of screen, pass row and column
  943.         INVOKE  SetCurPos, 0, 0
  944.  
  945.  
  946.         ; Exec specified program
  947.         INVOKE  Exec,
  948.                 ADDR Fspec[2],          ; File spec
  949.                 ADDR pb,                ; Parameter block structure
  950.                 NewBreak,               ; New handlers for CTRL+BREAK,
  951.                 NewCtrlC,               ;   CTRL+C,
  952.                 NewCritErr              ;   and Critical Error
  953.  
  954.  
  955.         .IF     ax != -1                ; If successful:
  956.  
  957.         ; Convert return code to string
  958.         ; Pass return code (AX) and address of string buffer
  959.         INVOKE  BinToHex, ax, ADDR Recode
  960.  
  961.         ; Update video structure
  962.         INVOKE  GetVidConfig
  963.  
  964.         Box CLKROW, CLKCOL-1, CLKROW, CLKCOL+17 ; Highlight on-screen clock
  965.         Box vconfig.rows, 0, vconfig.rows, 79   ; Highlight bottom row
  966.         mov     dl, vconfig.rows
  967.  
  968.         ; Display return code at bottom
  969.         INVOKE StrWrite, dx, 0, ADDR RetMsg
  970.  
  971.         ; Wait for keypress
  972.         INVOKE  Press
  973.         .ELSE
  974.         mov     ax, 0E07h               ; Write ASCII 7 character
  975.         int     10h                     ;   (bell) to console
  976.         .ENDIF
  977.  
  978.         ret
  979.  
  980. ExecPgm ENDP
  981.  
  982.  
  983.  
  984. ;* The following three procedures are primitive handlers for Interrupt 1Bh
  985. ;* (CTRL+BREAK), Interrupt 23h (CTRL+C), and Interrupt 24h (Critical Error).
  986. ;* The purpose of an interrupt handler in this context is to prevent termina-
  987. ;* tion of both parent and child processes when the interrupt is invoked.
  988. ;* Such handlers often set flags to signal to a process that the interrupt
  989. ;* has been called.
  990.  
  991. ;* NewBreak - Handler for Interrupt 1Bh.
  992.  
  993. NewBreak PROC   FAR
  994.  
  995.         sti                             ; Reenable interrupts
  996.         push    ax                      ; Preserve AX register
  997.         mov     al, 20h                 ; Send end-of-interrupt signal
  998.         out     20h, al                 ;   to interrupt controller
  999.         pop     ax                      ; Recover AX register
  1000.         iret                            ; Return from handler
  1001.                                         ;   without taking action
  1002. NewBreak ENDP
  1003.  
  1004.  
  1005. ;* NewCtrlC - Handler for Interrupt 23h.
  1006.  
  1007. NewCtrlC PROC   FAR
  1008.  
  1009.         iret                            ; Return from handler
  1010.                                         ;   without taking action
  1011. NewCtrlC ENDP
  1012.  
  1013.  
  1014. ;* NewCritErr - Handler for Interrupt 24h.
  1015.  
  1016. NewCritErr PROC FAR
  1017.  
  1018.         sub     al, al                  ; Tell DOS to ignore error
  1019.         iret                            ; Return from handler
  1020.                                         ;   without taking action
  1021. NewCritErr ENDP
  1022.  
  1023.         END
  1024.